#include "channel.h"     // 信道管理模块封装
#include "data_redis.h"  // redis数据管理客户端封装
#include "etcd.h"        // 服务注册模块封装
#include "logger.h"      // 日志模块封装
#include "thread_pool.h" // 线程池封装

#include "connection.h"

#include "base.pb.h"    // protobuf框架代码
#include "file.pb.h"    // protobuf框架代码
#include "friend.pb.h"  // protobuf框架代码
#include "gateway.pb.h" // protobuf框架代码
#include "message.pb.h" // protobuf框架代码
#include "notify.pb.h"
#include "speech.pb.h"    // protobuf框架代码
#include "transmite.pb.h" // protobuf框架代码
#include "user.pb.h"      // protobuf框架代码

#include "httplib.h"
#include <cstddef>
#include <thread>

#define MEDIA_WEBSOCKET_PORT 9002

#define GET_PHONE_VERIFY_CODE "/service/user/get_phone_verify_code"
#define USERNAME_REGISTER     "/service/user/username_register"
#define USERNAME_LOGIN        "/service/user/username_login"
#define PHONE_REGISTER        "/service/user/phone_register"
#define PHONE_LOGIN           "/service/user/phone_login"
#define GET_USERINFO          "/service/user/get_user_info"
#define SET_USER_AVATAR       "/service/user/set_avatar"
#define SET_USER_NICKNAME     "/service/user/set_nickname"
#define SET_USER_DESC         "/service/user/set_description"
#define SET_USER_PHONE        "/service/user/set_phone"
#define SET_USER_PASSWORD     "/service/user/set_password"

#define FRIEND_GET_LIST       "/service/friend/get_friend_list"
#define FRIEND_APPLY          "/service/friend/add_friend_apply"
#define FRIEND_APPLY_PROCESS  "/service/friend/add_friend_process"
#define FRIEND_REMOVE         "/service/friend/remove_friend"
#define FRIEND_SEARCH         "/service/friend/search_friend"
#define FRIEND_GET_PENDING_EV "/service/friend/get_pending_friend_events"

#define CSS_GET_LIST   "/service/friend/get_chat_session_list"
#define CSS_CREATE     "/service/friend/create_chat_session"
#define CSS_GET_MEMBER "/service/friend/get_chat_session_member"
#define SET_CSS_NAME   "/service/friend/set_chat_session_name"
#define QUIT_CSS       "/service/friend/quit_chat_session"
#define ADD_CSS_MEMBER "/service/friend/add_chat_session_member"

#define MSG_GET_RANGE  "/service/message_storage/get_history"
#define MSG_GET_RECENT "/service/message_storage/get_recent"
#define MSG_KEY_SEARCH "/service/message_storage/search_history"
#define NEW_MESSAGE    "/service/message_transmit/new_message"

#define FILE_GET_SINGLE "/service/file/get_single_file"
#define FILE_GET_MULTI  "/service/file/get_multi_file"
#define FILE_PUT_SINGLE "/service/file/put_single_file"
#define FILE_PUT_MULTI  "/service/file/put_multi_file"

#define SPEECH_RECOGNITION "/service/speech/recognition"

#define COMMUNICATE_INVITE "/service/communicate/invite"
#define COMMUNICATE_AGREE  "/service/communicate/agree"
#define COMMUNICATE_REFUSE "/service/communicate/refuse"

class GatewayServer
{
public:
    using ptr = std::shared_ptr<GatewayServer>;
    GatewayServer(int websocket_port,
                  int http_port,
                  const std::shared_ptr<sw::redis::Redis> &redis_client,
                  const ServiceManager::ptr &channels,
                  const Discover::ptr &service_discoverer,
                  const std::string user_service_name,
                  const std::string file_service_name,
                  const std::string speech_service_name,
                  const std::string message_service_name,
                  const std::string transmite_service_name,
                  const std::string friend_service_name)
        : _redis_session(std::make_shared<Session>(redis_client)),
          _redis_status(std::make_shared<Status>(redis_client)),
          _mm_channels(channels),
          _service_discoverer(service_discoverer),
          _user_service_name(user_service_name),
          _file_service_name(file_service_name),
          _speech_service_name(speech_service_name),
          _message_service_name(message_service_name),
          _transmite_service_name(transmite_service_name),
          _friend_service_name(friend_service_name),
          _connections(std::make_shared<Connection>()),
          _media_conns(std::make_shared<Connection>())
    {
        _ws_server.set_access_channels(websocketpp::log::alevel::none);
        _ws_server.init_asio();
        _ws_server.set_open_handler(std::bind(&GatewayServer::onOpen, this, std::placeholders::_1));
        _ws_server.set_close_handler(std::bind(&GatewayServer::onClose, this, std::placeholders::_1));
        _ws_server.set_message_handler(std::bind(&GatewayServer::onMessage, this, std::placeholders::_1, std::placeholders::_2));
        _ws_server.set_reuse_addr(true);
        _ws_server.listen(websocket_port);
        _ws_server.start_accept();

        _ws_media_server.set_access_channels(websocketpp::log::alevel::none);
        _ws_media_server.init_asio();
        _ws_media_server.set_open_handler(std::bind(&GatewayServer::onMediaOpen, this, std::placeholders::_1));
        _ws_media_server.set_close_handler(std::bind(&GatewayServer::onMediaClose, this, std::placeholders::_1));
        _ws_media_server.set_message_handler(std::bind(&GatewayServer::onMediaMessage, this, std::placeholders::_1, std::placeholders::_2));
        _ws_media_server.set_reuse_addr(true);
        _ws_media_server.listen(MEDIA_WEBSOCKET_PORT);
        _ws_media_server.start_accept();

        // 映射请求URL与请求方法
        _http_server.Post(GET_PHONE_VERIFY_CODE, (httplib::Server::Handler)std::bind(&GatewayServer::GetPhoneVerifyCode, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(USERNAME_REGISTER, (httplib::Server::Handler)std::bind(&GatewayServer::UserRegister, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(USERNAME_LOGIN, (httplib::Server::Handler)std::bind(&GatewayServer::UserLogin, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(PHONE_REGISTER, (httplib::Server::Handler)std::bind(&GatewayServer::PhoneRegister, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(PHONE_LOGIN, (httplib::Server::Handler)std::bind(&GatewayServer::PhoneLogin, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(GET_USERINFO, (httplib::Server::Handler)std::bind(&GatewayServer::GetUserInfo, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(SET_USER_AVATAR, (httplib::Server::Handler)std::bind(&GatewayServer::SetUserAvatar, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(SET_USER_NICKNAME, (httplib::Server::Handler)std::bind(&GatewayServer::SetUserNickname, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(SET_USER_DESC, (httplib::Server::Handler)std::bind(&GatewayServer::SetUserDescription, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(SET_USER_PHONE, (httplib::Server::Handler)std::bind(&GatewayServer::SetUserPhoneNumber, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(SET_USER_PASSWORD, (httplib::Server::Handler)std::bind(&GatewayServer::SetUserPassword, this, std::placeholders::_1, std::placeholders::_2));

        _http_server.Post(FRIEND_GET_LIST, (httplib::Server::Handler)std::bind(&GatewayServer::GetFriendList, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(FRIEND_APPLY, (httplib::Server::Handler)std::bind(&GatewayServer::FriendAdd, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(FRIEND_APPLY_PROCESS, (httplib::Server::Handler)std::bind(&GatewayServer::FriendAddProcess, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(FRIEND_REMOVE, (httplib::Server::Handler)std::bind(&GatewayServer::FriendRemove, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(FRIEND_SEARCH, (httplib::Server::Handler)std::bind(&GatewayServer::FriendSearch, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(FRIEND_GET_PENDING_EV, (httplib::Server::Handler)std::bind(&GatewayServer::GetPendingFriendEventList, this, std::placeholders::_1, std::placeholders::_2));

        _http_server.Post(CSS_GET_LIST, (httplib::Server::Handler)std::bind(&GatewayServer::GetChatSessionList, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(CSS_CREATE, (httplib::Server::Handler)std::bind(&GatewayServer::ChatSessionCreate, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(CSS_GET_MEMBER, (httplib::Server::Handler)std::bind(&GatewayServer::GetChatSessionMember, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(SET_CSS_NAME, (httplib::Server::Handler)std::bind(&GatewayServer::SetChatSessionName, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(QUIT_CSS, (httplib::Server::Handler)std::bind(&GatewayServer::QuitChatSession, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(ADD_CSS_MEMBER, (httplib::Server::Handler)std::bind(&GatewayServer::AddChatSessionMember, this, std::placeholders::_1, std::placeholders::_2));

        _http_server.Post(MSG_GET_RANGE, (httplib::Server::Handler)std::bind(&GatewayServer::GetHistoryMsg, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(MSG_GET_RECENT, (httplib::Server::Handler)std::bind(&GatewayServer::GetRecentMsg, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(MSG_KEY_SEARCH, (httplib::Server::Handler)std::bind(&GatewayServer::MsgSearch, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(NEW_MESSAGE, (httplib::Server::Handler)std::bind(&GatewayServer::NewMessage, this, std::placeholders::_1, std::placeholders::_2));

        _http_server.Post(FILE_GET_SINGLE, (httplib::Server::Handler)std::bind(&GatewayServer::GetSingleFile, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(FILE_GET_MULTI, (httplib::Server::Handler)std::bind(&GatewayServer::GetMultiFile, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(FILE_PUT_SINGLE, (httplib::Server::Handler)std::bind(&GatewayServer::PutSingleFile, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(FILE_PUT_MULTI, (httplib::Server::Handler)std::bind(&GatewayServer::PutMultiFile, this, std::placeholders::_1, std::placeholders::_2));

        _http_server.Post(SPEECH_RECOGNITION, (httplib::Server::Handler)std::bind(&GatewayServer::SpeechRecognition, this, std::placeholders::_1, std::placeholders::_2));

        _http_server.Post(COMMUNICATE_INVITE, (httplib::Server::Handler)std::bind(&GatewayServer::InviteCommunicate, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(COMMUNICATE_AGREE, (httplib::Server::Handler)std::bind(&GatewayServer::AgreeCommunicate, this, std::placeholders::_1, std::placeholders::_2));
        _http_server.Post(COMMUNICATE_REFUSE, (httplib::Server::Handler)std::bind(&GatewayServer::RefuseCommunicate, this, std::placeholders::_1, std::placeholders::_2));

        _http_server.new_task_queue = []()
        {
            return new httplib::ThreadPool(8);
        };

        _http_thread = std::thread([this, http_port]()
                                   { _http_server.listen("0.0.0.0", http_port); });
        _http_thread.detach();

        _ws_media_thread = std::thread([=]()
                                       { _ws_media_server.run(); });
        _ws_media_thread.detach();

        ThreadPoolCtrl::getInstance().initialize();
    }

    void start()
    {
        _ws_server.run();
    }

private:
    void onOpen(websocketpp::connection_hdl hdl)
    {
        LOG_DEBUG("websocket长连接建立成功 {}", (size_t)_ws_server.get_con_from_hdl(hdl).get());
    }

    void onMediaOpen(websocketpp::connection_hdl hdl)
    {
        LOG_DEBUG("media websocket长连接建立成功 {}", (size_t)_ws_media_server.get_con_from_hdl(hdl).get());
    }

    void onClose(websocketpp::connection_hdl hdl)
    {
        // 长连接断开时做的清理工作
        // 0. 通过连接对象，获取对应的用户ID与登录会话ID
        auto conn = _ws_server.get_con_from_hdl(hdl);
        std::string uid, ssid;
        bool ret = _connections->client(conn, uid, ssid);
        if (ret == false)
        {
            LOG_WARN("长连接断开，未找到长连接对应的客户端信息！");
            return;
        }
        // 1. 移除登录会话信息
        _redis_session->remove(ssid);
        // 2. 移除登录状态信息
        _redis_status->remove(uid);
        // 3. 移除长连接管理数据
        _connections->remove(conn);
        LOG_DEBUG("{} {} {} 长连接断开，清理缓存数据!", ssid, uid, (size_t)conn.get());
    }

    void onMediaClose(websocketpp::connection_hdl hdl)
    {
        // 长连接断开时做的清理工作
        // 0. 通过连接对象，获取对应的用户ID与登录会话ID
        auto conn = _ws_media_server.get_con_from_hdl(hdl);
        std::string uid, ssid;
        bool ret = _media_conns->client(conn, uid, ssid);
        if (ret == false)
        {
            LOG_WARN("长连接断开，未找到长连接对应的客户端信息！");
            return;
        }
        // 1. 移除流媒体长连接管理数据
        _media_conns->remove(conn);
        LOG_DEBUG("{} {} {} 流媒体长连接断开，清理缓存数据!", ssid, uid, (size_t)conn.get());
    }

    void keepAlive(server_t::connection_ptr conn)
    {
        if (!conn || conn->get_state() != websocketpp::session::state::value::open)
        {
            LOG_DEBUG("非正常连接状态，结束连接保活");
            return;
        }
        conn->ping("");
        _ws_server.set_timer(60000, std::bind(&GatewayServer::keepAlive, this, conn));
    }

    void onMessage(websocketpp::connection_hdl hdl, server_t::message_ptr msg)
    {
        // 收到第一条消息后，根据消息中的会话ID进行身份识别，将客户端长连接添加管理
        // 1. 取出长连接对应的连接对象
        auto conn = _ws_server.get_con_from_hdl(hdl);
        // 2. 针对消息内容进行反序列化 -- ClientAuthenticationReq -- 提取登录会话ID
        ljm::ClientAuthenticationReq request;
        bool ret = request.ParseFromString(msg->get_payload());
        if (!ret)
        {
            LOG_ERROR("长连接身份识别失败：正文反序列化失败！");
            _ws_server.close(hdl, websocketpp::close::status::unsupported_data, "正文反序列化失败!");
            return;
        }
        // 3. 在会话信息缓存中，查找会话信息
        std::string ssid = request.session_id();
        auto uid = _redis_session->uid(ssid);
        // 4. 会话信息不存在则关闭连接
        if (!uid)
        {
            LOG_ERROR("长连接身份识别失败：未找到会话信息 {}！", ssid);
            _ws_server.close(hdl, websocketpp::close::status::unsupported_data, "未找到会话信息!");
            return;
        }
        // 5. 会话信息存在，则添加长连接管理
        _connections->insert(conn, *uid, ssid);
        LOG_DEBUG("新增长连接管理：{}-{}-{}", ssid, *uid, (size_t)conn.get());
        keepAlive(conn);
    }

    void onMediaMessage(websocketpp::connection_hdl hdl, server_t::message_ptr msg)
    {
        LOG_DEBUG("收到流媒体包!");
        // 收到第一条消息后，根据消息中的会话ID进行身份识别，将客户端长连接添加管理
        // 1. 取出长连接对应的连接对象
        auto conn = _ws_media_server.get_con_from_hdl(hdl);
        // 2. 针对消息内容进行反序列化 -- MediaData -- 提取登录会话ID
        ljm::MediaData data;
        bool ret = data.ParseFromString(msg->get_payload());
        if (!ret)
        {
            LOG_ERROR("流媒体长连接识别失败：正文反序列化失败！");
            _ws_media_server.close(hdl, websocketpp::close::status::unsupported_data, "正文反序列化失败!");
            return;
        }
        // 3. 在会话信息缓存中，查找会话信息
        std::string ssid = data.session_id();
        auto uid = _redis_session->uid(ssid);
        // 4. 会话信息不存在则关闭连接
        if (!uid)
        {
            LOG_ERROR("流媒体长连接身份识别失败：未找到会话信息 {}！", ssid);
            _ws_media_server.close(hdl, websocketpp::close::status::unsupported_data, "未找到会话信息!");
            return;
        }
        // 5. 查看数据类型---按不同类型做不同处理
        if (data.type() == "setup")
        {
            // 建立连接信息
            _media_conns->insert(conn, *uid, ssid);
            LOG_DEBUG("新增流媒体长连接管理：{}-{}-{}", ssid, *uid, (size_t)conn.get());
        }
        else if (data.type() == "video" || data.type() == "audio")
        {
            // 音频或者视频数据就直接进行转发
            for (int i = 0; i < data.receiver_id_size(); ++i)
            {
                auto recv_conn = _media_conns->connection(data.receiver_id(i));
                if (!recv_conn)
                {
                    LOG_DEBUG("未找到接收者 {} 长连接", data.receiver_id(i));
                    continue;
                }

                if (!recv_conn || recv_conn->get_state() != websocketpp::session::state::open)
                {
                    LOG_DEBUG("接收者 {} 连接已关闭", data.receiver_id(i));
                    _media_conns->remove(conn); // 清理无效连接
                    continue;
                }

                // 安全发送
                try
                {
                    recv_conn->send(data.SerializeAsString(), websocketpp::frame::opcode::binary);
                    LOG_DEBUG("发送成功: {}", (size_t)recv_conn.get());
                }
                catch (const std::exception &e)
                {
                    LOG_ERROR("发送失败: {}", e.what());
                    _media_conns->remove(conn);
                }
            }
        }
    }

    httplib::Response GetPhoneVerifyCodeTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::PhoneVerifyCodeReq req;
        ljm::PhoneVerifyCodeRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("获取短信验证码请求正文反序列化失败！");
            return err_response("获取短信验证码请求正文反序列化失败！");
        }
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetPhoneVerifyCode(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetPhoneVerifyCode(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetPhoneVerifyCodeTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response UserRegisterTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::UserRegisterReq req;
        ljm::UserRegisterRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户名注册请求正文反序列化失败！");
            return err_response("用户名注册请求正文反序列化失败！");
        }
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.UserRegister(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void UserRegister(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::UserRegisterTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response UserLoginTask(const httplib::Request &request, httplib::Response &response)
    {
        LOG_DEBUG("开始处理登录任务");
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::UserLoginReq req;
        ljm::UserLoginRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户登录请求正文反序列化失败！");
            return err_response("用户登录请求正文反序列化失败！");
        }
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.UserLogin(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void UserLogin(const httplib::Request &request, httplib::Response &response)
    {
        LOG_DEBUG("收到登录请求");
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::UserLoginTask, this, request, response);
        response = futrue.get();
    }

    void PhoneRegister(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::PhoneRegisterReq req;
        ljm::PhoneRegisterRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("手机号注册请求正文反序列化失败！");
            return err_response("手机号注册请求正文反序列化失败！");
        }
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.PhoneRegister(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
    }

    void PhoneLogin(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::PhoneLoginReq req;
        ljm::PhoneLoginRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> void
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("手机号登录请求正文反序列化失败！");
            return err_response("手机号登录请求正文反序列化失败！");
        }
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.PhoneLogin(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
    }

    httplib::Response GetUserInfoTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::GetUserInfoReq req;
        ljm::GetUserInfoRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("获取用户信息请求正文反序列化失败！");
            return err_response("获取用户信息请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetUserInfo(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetUserInfo(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetUserInfoTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response SetUserAvatarTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::SetUserAvatarReq req;
        ljm::SetUserAvatarRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户头像设置请求正文反序列化失败！");
            return err_response("用户头像设置请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetUserAvatar(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void SetUserAvatar(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::SetUserAvatarTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response SetUserNicknameTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::SetUserNicknameReq req;
        ljm::SetUserNicknameRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户昵称设置请求正文反序列化失败！");
            return err_response("用户昵称设置请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetUserNickname(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void SetUserNickname(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::SetUserNicknameTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response SetUserDescriptionTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::SetUserDescriptionReq req;
        ljm::SetUserDescriptionRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户签名设置请求正文反序列化失败！");
            return err_response("用户签名设置请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetUserDescription(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void SetUserDescription(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::SetUserDescriptionTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response SetUserPhoneNumberTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::SetUserPhoneNumberReq req;
        ljm::SetUserPhoneNumberRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户手机号设置请求正文反序列化失败！");
            return err_response("用户手机号设置请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetUserPhoneNumber(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void SetUserPhoneNumber(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::SetUserPhoneNumberTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response SetUserPasswordTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::SetUserPasswordReq req;
        ljm::SetUserPasswordRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户密码设置请求正文反序列化失败！");
            return err_response("用户密码设置请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetUserPassword(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 3. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void SetUserPassword(const httplib::Request &request, httplib::Response &response)
    {
        LOG_DEBUG("收到修改密码请求!");
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::SetUserPasswordTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response GetFriendListTask(const httplib::Request &request, httplib::Response &response)
    {
        LOG_DEBUG("收到获取好友列表请求");
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::GetFriendListReq req;
        ljm::GetFriendListRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("获取好友列表请求正文反序列化失败！");
            return err_response("获取好友列表请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }

        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetFriendList(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }
        // 4. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetFriendList(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetFriendListTask, this, request, response);
        response = futrue.get();
    }

    std::shared_ptr<ljm::GetUserInfoRsp> _GetUserInfo(const std::string &rid, const std::string &uid)
    {
        ljm::GetUserInfoReq req;
        auto rsp = std::make_shared<ljm::GetUserInfoRsp>();
        req.set_request_id(rid);
        req.set_user_id(uid);
        // 2. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_user_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return std::shared_ptr<ljm::GetUserInfoRsp>();
        }
        ljm::UserService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetUserInfo(&cntl, &req, rsp.get(), nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return std::shared_ptr<ljm::GetUserInfoRsp>();
        }
        return rsp;
    }

    httplib::Response FriendAddTask(const httplib::Request &request, httplib::Response &response)
    {
        // 好友申请的业务处理中，好友子服务其实只是在数据库创建了申请事件
        // 网关需要做的事情：当好友子服务将业务处理完毕后，如果处理是成功的--需要通知被申请方
        // 1. 正文的反序列化，提取关键要素：登录会话ID
        ljm::FriendAddReq req;
        ljm::FriendAddRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("申请好友请求正文反序列化失败！");
            return err_response("申请好友请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.FriendAdd(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }
        // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向被申请放进行好友申请事件通知
        auto conn = _connections->connection(req.respondent_id());
        if (rsp.success() && conn)
        {
            LOG_DEBUG("找到被申请人 {} 长连接，对其进行好友申请通知", req.respondent_id());
            auto user_rsp = _GetUserInfo(req.request_id(), *uid);
            if (!user_rsp)
            {
                LOG_ERROR("{} 获取当前客户端用户信息失败！", req.request_id());
                return err_response("获取当前客户端用户信息失败！");
            }
            ljm::NotifyMessage notify;
            notify.set_notify_type(ljm::NotifyType::FRIEND_ADD_APPLY_NOTIFY);
            notify.mutable_friend_add_apply()->mutable_user_info()->CopyFrom(user_rsp->user_info());
            conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void FriendAdd(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::FriendAddTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response FriendAddProcessTask(const httplib::Request &request, httplib::Response &response)
    {
        // 好友申请的处理-----
        ljm::FriendAddProcessReq req;
        ljm::FriendAddProcessRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("好友申请处理请求正文反序列化失败！");
            return err_response("好友申请处理请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.FriendAddProcess(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }

        // 处理成功
        if (rsp.success())
        {
            auto process_user_rsp = _GetUserInfo(req.request_id(), *uid);
            if (!process_user_rsp)
            {
                LOG_ERROR("{} 获取用户信息失败！", req.request_id());
                return err_response("获取用户信息失败！");
            }
            auto apply_user_rsp = _GetUserInfo(req.request_id(), req.apply_user_id());
            if (!process_user_rsp)
            {
                LOG_ERROR("{} 获取用户信息失败！", req.request_id());
                return err_response("获取用户信息失败！");
            }
            auto process_conn = _connections->connection(*uid);
            if (process_conn)
                LOG_DEBUG("找到处理人的长连接！");
            else
                LOG_DEBUG("未找到处理人的长连接！");
            auto apply_conn = _connections->connection(req.apply_user_id());
            if (apply_conn)
                LOG_DEBUG("找到申请人的长连接！");
            else
                LOG_DEBUG("未找到申请人的长连接！");
            // 4. 将处理结果给申请人进行通知
            if (apply_conn)
            {
                ljm::NotifyMessage notify;
                notify.set_notify_type(ljm::NotifyType::FRIEND_ADD_PROCESS_NOTIFY);
                auto process_result = notify.mutable_friend_process_result();
                process_result->mutable_user_info()->CopyFrom(process_user_rsp->user_info());
                process_result->set_agree(req.agree());
                apply_conn->send(notify.SerializeAsString(),
                                 websocketpp::frame::opcode::value::binary);
                LOG_DEBUG("对申请人进行申请处理结果通知！");
            }
            // 5. 若处理结果是同意 --- 会伴随着单聊会话的创建 -- 因此需要对双方进行会话创建的通知
            if (req.agree() && apply_conn)
            {
                // 对申请人的通知---会话信息就是处理人信息
                ljm::NotifyMessage notify;
                notify.set_notify_type(ljm::NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                auto chat_session = notify.mutable_new_chat_session_info();
                chat_session->mutable_chat_session_info()->set_single_chat_friend_id(*uid);
                chat_session->mutable_chat_session_info()->set_chat_session_id(rsp.new_session_id());
                chat_session->mutable_chat_session_info()->set_chat_session_name(process_user_rsp->user_info().nickname());
                chat_session->mutable_chat_session_info()->set_avatar(process_user_rsp->user_info().avatar());
                apply_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                LOG_DEBUG("对申请人进行会话创建通知！");
            }
            if (req.agree() && process_conn)
            {
                // 对处理人的通知 --- 会话信息就是申请人信息
                ljm::NotifyMessage notify;
                notify.set_notify_type(ljm::NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                auto chat_session = notify.mutable_new_chat_session_info();
                chat_session->mutable_chat_session_info()->set_single_chat_friend_id(req.apply_user_id());
                chat_session->mutable_chat_session_info()->set_chat_session_id(rsp.new_session_id());
                chat_session->mutable_chat_session_info()->set_chat_session_name(apply_user_rsp->user_info().nickname());
                chat_session->mutable_chat_session_info()->set_avatar(apply_user_rsp->user_info().avatar());
                process_conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                LOG_DEBUG("对处理人进行会话创建通知！");
            }
        }
        // 6. 对客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void FriendAddProcess(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::FriendAddProcessTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response FriendRemoveTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 正文的反序列化，提取关键要素：登录会话ID
        ljm::FriendRemoveReq req;
        ljm::FriendRemoveRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("删除好友请求正文反序列化失败！");
            return err_response("删除好友请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.FriendRemove(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }
        // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向被申请放进行好友申请事件通知
        auto conn = _connections->connection(req.peer_id());
        if (rsp.success() && conn)
        {
            LOG_ERROR("对被删除人 {} 进行好友删除通知！", req.peer_id());
            ljm::NotifyMessage notify;
            notify.set_notify_type(ljm::NotifyType::FRIEND_REMOVE_NOTIFY);
            notify.mutable_friend_remove()->set_user_id(*uid);
            conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void FriendRemove(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::FriendRemoveTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response FriendSearchTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::FriendSearchReq req;
        ljm::FriendSearchRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户搜索请求正文反序列化失败！");
            return err_response("用户搜索请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.FriendSearch(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void FriendSearch(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::FriendSearchTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response GetPendingFriendEventListTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::GetPendingFriendEventListReq req;
        ljm::GetPendingFriendEventListRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("获取待处理好友申请请求正文反序列化失败！");
            return err_response("获取待处理好友申请请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetPendingFriendEventList(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetPendingFriendEventList(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetPendingFriendEventListTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response GetChatSessionListTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::GetChatSessionListReq req;
        ljm::GetChatSessionListRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("获取聊天会话列表请求正文反序列化失败！");
            return err_response("获取聊天会话列表请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetChatSessionList(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetChatSessionList(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetChatSessionListTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response GetChatSessionMemberTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::GetChatSessionMemberReq req;
        ljm::GetChatSessionMemberRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("获取聊天会话成员请求正文反序列化失败！");
            return err_response("获取聊天会话成员请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetChatSessionMember(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetChatSessionMember(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetChatSessionMemberTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response ChatSessionCreateTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::ChatSessionCreateReq req;
        ljm::ChatSessionCreateRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("创建聊天会话请求正文反序列化失败！");
            return err_response("创建聊天会话请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.ChatSessionCreate(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }
        // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向被创建群聊的用户进行事件通知
        if (rsp.success())
        {
            for (int i = 0; i < req.member_id_list_size(); i++)
            {
                auto conn = _connections->connection(req.member_id_list(i));
                if (!conn)
                {
                    LOG_DEBUG("未找到群聊成员 {} 长连接", req.member_id_list(i));
                    continue;
                }
                ljm::NotifyMessage notify;
                notify.set_notify_type(ljm::NotifyType::CHAT_SESSION_CREATE_NOTIFY);
                auto chat_session = notify.mutable_new_chat_session_info();
                chat_session->mutable_chat_session_info()->CopyFrom(rsp.chat_session_info());
                conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                LOG_DEBUG("对群聊成员 {} 进行会话创建通知", req.member_id_list(i));
            }
        }
        // 5. 向客户端进行响应
        rsp.clear_chat_session_info();
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void ChatSessionCreate(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::ChatSessionCreateTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response GetHistoryMsgTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::GetHistoryMsgReq req;
        ljm::GetHistoryMsgRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("获取区间消息请求正文反序列化失败！");
            return err_response("获取区间消息请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_message_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::MsgStorageService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetHistoryMsg(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 消息存储子服务调用失败！", req.request_id());
            return err_response("消息存储子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetHistoryMsg(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetHistoryMsgTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response GetRecentMsgTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::GetRecentMsgReq req;
        ljm::GetRecentMsgRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("获取最近消息请求正文反序列化失败！");
            return err_response("获取最近消息请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_message_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::MsgStorageService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetRecentMsg(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 消息存储子服务调用失败！", req.request_id());
            return err_response("消息存储子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetRecentMsg(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetRecentMsgTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response MsgSearchTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::MsgSearchReq req;
        ljm::MsgSearchRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("消息搜索请求正文反序列化失败！");
            return err_response("消息搜索请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_message_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::MsgStorageService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.MsgSearch(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 消息存储子服务调用失败！", req.request_id());
            return err_response("消息存储子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void MsgSearch(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::MsgSearchTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response GetSingleFileTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::GetSingleFileReq req;
        ljm::GetSingleFileRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("单文件下载请求正文反序列化失败！");
            return err_response("单文件下载请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_file_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FileService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetSingleFile(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 文件存储子服务调用失败！", req.request_id());
            return err_response("文件存储子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetSingleFile(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetSingleFileTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response GetMultiFileTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::GetMultiFileReq req;
        ljm::GetMultiFileRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("单文件下载请求正文反序列化失败！");
            return err_response("单文件下载请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_file_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FileService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetMultiFile(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 文件存储子服务调用失败！", req.request_id());
            return err_response("文件存储子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void GetMultiFile(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::GetMultiFileTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response PutSingleFileTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::PutSingleFileReq req;
        ljm::PutSingleFileRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("单文件上传请求正文反序列化失败！");
            return err_response("单文件上传请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_file_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FileService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.PutSingleFile(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 文件存储子服务调用失败！", req.request_id());
            return err_response("文件存储子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void PutSingleFile(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::PutSingleFileTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response PutMultiFileTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::PutMultiFileReq req;
        ljm::PutMultiFileRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("批量文件上传请求正文反序列化失败！");
            return err_response("批量文件上传请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_file_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FileService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.PutMultiFile(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 文件存储子服务调用失败！", req.request_id());
            return err_response("文件存储子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void PutMultiFile(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::PutMultiFileTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response SpeechRecognitionTask(const httplib::Request &request, httplib::Response &response)
    {
        LOG_DEBUG("收到语音转文字请求！");
        ljm::SpeechRecognitionReq req;
        ljm::SpeechRecognitionRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("语音识别请求正文反序列化失败！");
            return err_response("语音识别请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_speech_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::SpeechService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SpeechRecognition(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 语音识别子服务调用失败！", req.request_id());
            return err_response("语音识别子服务调用失败！");
        }
        // 5. 向客户端进行响应
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void SpeechRecognition(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::SpeechRecognitionTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response NewMessageTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::NewMessageReq req;
        ljm::NewMessageRsp rsp;               // 这是给客户端的响应
        ljm::GetTransmitTargetRsp target_rsp; // 这是请求子服务的响应
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("新消息请求正文反序列化失败！");
            return err_response("新消息请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_transmite_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::MsgTransmitService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.GetTransmitTarget(&cntl, &req, &target_rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 消息转发子服务调用失败！", req.request_id());
            return err_response("消息转发子服务调用失败！");
        }
        // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向被申请放进行好友申请事件通知
        if (target_rsp.success())
        {
            for (int i = 0; i < target_rsp.target_id_list_size(); i++)
            {
                std::string notify_uid = target_rsp.target_id_list(i);
                if (notify_uid == *uid)
                    continue; // 不通知自己
                auto conn = _connections->connection(notify_uid);
                if (!conn)
                {
                    continue;
                }
                ljm::NotifyMessage notify;
                notify.set_notify_type(ljm::NotifyType::CHAT_MESSAGE_NOTIFY);
                auto msg_info = notify.mutable_new_message_info();
                msg_info->mutable_message_info()->CopyFrom(target_rsp.message());
                conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
            }
        }
        // 5. 向客户端进行响应
        rsp.set_request_id(req.request_id());
        rsp.set_success(target_rsp.success());
        rsp.set_errmsg(target_rsp.errmsg());
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void NewMessage(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(MEDIUM, &GatewayServer::NewMessageTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response SetChatSessionNameTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::SetChatSessionNameReq req;
        ljm::SetChatSessionNameRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户修改群聊名称请求正文反序列化失败！");
            return err_response("用户修改群聊名称请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.SetChatSessionName(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向被申请放进行好友申请事件通知
        if (rsp.success())
        {
            ljm::GetChatSessionMemberReq greq;
            ljm::GetChatSessionMemberRsp grsp;
            greq.set_request_id(req.request_id());
            greq.set_user_id(req.user_id());
            greq.set_chat_session_id(req.chat_session_id());
            auto channel = _mm_channels->getService(_friend_service_name);
            if (!channel)
            {
                LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
                return err_response("未找到可提供业务处理的用户子服务节点！");
            }
            ljm::FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetChatSessionMember(&cntl, &greq, &grsp, nullptr);
            if (cntl.Failed())
            {
                LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
                return err_response("用户子服务调用失败！");
            }
            for (int i = 0; i < grsp.member_info_list_size(); i++)
            {
                std::string guid = grsp.member_info_list(i).user_id();
                if (guid == uid)
                    continue;

                auto conn = _connections->connection(guid);
                if (!conn)
                {
                    LOG_DEBUG("未找到群聊成员 {} 长连接", guid);
                    continue;
                }
                ljm::NotifyMessage notify;
                notify.set_notify_type(ljm::NotifyType::SET_CHAT_SESSION_NAME_NOTIFY);
                notify.mutable_new_chat_session_name_info()->set_chat_session_id(req.chat_session_id());
                notify.mutable_new_chat_session_name_info()->set_new_chat_session_name(req.chat_session_name());
                conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                LOG_DEBUG("对群聊成员 {} 进行会话名称修改通知", guid);
            }
        }
        // 5. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void SetChatSessionName(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::SetChatSessionNameTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response QuitChatSessionTask(const httplib::Request &request, httplib::Response &response)
    {
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::QuitChatSessionReq req;
        ljm::QuitChatSessionRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户退出群聊请求正文反序列化失败！");
            return err_response("用户退出群聊请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给用户子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.QuitChatSession(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
            return err_response("用户子服务调用失败！");
        }
        // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向被申请放进行好友申请事件通知
        if (rsp.success())
        {
            // 获取退出群聊用户信息
            auto user_rsp = _GetUserInfo(req.request_id(), req.user_id());
            // 获取群聊成员列表
            ljm::GetChatSessionMemberReq greq;
            ljm::GetChatSessionMemberRsp grsp;
            greq.set_request_id(req.request_id());
            greq.set_user_id(req.user_id());
            greq.set_chat_session_id(req.chat_session_id());
            auto channel = _mm_channels->getService(_friend_service_name);
            if (!channel)
            {
                LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
                return err_response("未找到可提供业务处理的用户子服务节点！");
            }
            ljm::FriendService_Stub stub(channel.get());
            brpc::Controller cntl;
            stub.GetChatSessionMember(&cntl, &greq, &grsp, nullptr);
            if (cntl.Failed())
            {
                LOG_ERROR("{} 用户子服务调用失败！", req.request_id());
                return err_response("用户子服务调用失败！");
            }
            for (int i = 0; i < grsp.member_info_list_size(); i++)
            {
                std::string guid = grsp.member_info_list(i).user_id();
                // if (guid == uid)
                //     continue;
                auto conn = _connections->connection(guid);
                if (!conn)
                {
                    LOG_DEBUG("未找到群聊成员 {} 长连接", guid);
                    continue;
                }
                ljm::NotifyMessage notify;
                notify.set_notify_type(ljm::NotifyType::QUIT_CHAT_SESSION_NOTIFY);
                notify.mutable_quit_chat_session_notify()->set_chat_session_id(req.chat_session_id());
                notify.mutable_quit_chat_session_notify()->set_user_name(user_rsp->user_info().nickname());
                conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                LOG_DEBUG("对群聊成员 {} 进行用户 {} 退出群聊通知", guid, user_rsp->user_info().user_id());
            }
        }
        // 5. 得到用户子服务的响应后，将响应内容进行序列化作为http响应正文
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void QuitChatSession(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::QuitChatSessionTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response AddChatSessionMemberTask(const httplib::Request &request, httplib::Response &response)
    {
        ljm::AddChatSessionMemberReq req;
        ljm::AddChatSessionMemberRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("向群聊会话添加新成员请求正文反序列化失败！");
            return err_response("向群聊会话添加新成员请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        req.set_user_id(*uid);
        // 3. 将请求转发给好友子服务进行业务处理
        auto channel = _mm_channels->getService(_friend_service_name);
        if (!channel)
        {
            LOG_ERROR("{} 未找到可提供业务处理的用户子服务节点！", req.request_id());
            return err_response("未找到可提供业务处理的用户子服务节点！");
        }
        ljm::FriendService_Stub stub(channel.get());
        brpc::Controller cntl;
        stub.AddChatSessionMember(&cntl, &req, &rsp, nullptr);
        if (cntl.Failed())
        {
            LOG_ERROR("{} 好友子服务调用失败！", req.request_id());
            return err_response("好友子服务调用失败！");
        }
        // 4. 若业务处理成功 --- 且获取被申请方长连接成功，则向被创建群聊的用户进行事件通知
        if (rsp.success())
        {
            for (int i = 0; i < req.member_id_list_size(); i++)
            {
                auto conn = _connections->connection(req.member_id_list(i));
                if (!conn)
                {
                    LOG_DEBUG("未找到需添加进群聊的成员 {} 长连接", req.member_id_list(i));
                    continue;
                }
                ljm::NotifyMessage notify;
                notify.set_notify_type(ljm::NotifyType::ADD_CHAT_SESSION_MEMBER_NOTIFY);
                auto add_chat_session_member_notify = notify.mutable_add_chat_session_member_notify();
                add_chat_session_member_notify->mutable_chat_session_info()->CopyFrom(rsp.chat_session_info());
                add_chat_session_member_notify->set_inviter_id(*uid);
                conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
                LOG_DEBUG("对群聊成员 {} 进行会话创建通知", req.member_id_list(i));
            }
        }
        // 5. 向客户端进行响应
        rsp.clear_chat_session_info();
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void AddChatSessionMember(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(LOW, &GatewayServer::AddChatSessionMemberTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response InviteCommunicateTask(const httplib::Request &request, httplib::Response &response)
    {
        LOG_DEBUG("收到申请通话请求申请!");
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::CommunicateReq req;
        ljm::CommunicateRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户申请通话请求正文反序列化失败！");
            return err_response("用户申请通话请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        // 3. 向好友发起通话邀请
        for (int i = 0; i < req.receiver_id_size(); ++i)
        {
            auto recv_id = req.receiver_id(i);
            auto conn = _connections->connection(recv_id);
            if (!conn)
            {
                LOG_DEBUG("未找到接收成员 {} 长连接", recv_id);
                continue;
            }
            ljm::NotifyMessage notify;
            notify.set_notify_type(ljm::NotifyType::COMMUNICATE_NOTIFY);
            notify.mutable_communicate_notify()->set_sender_id(*uid);
            notify.mutable_communicate_notify()->set_type("request");
            conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
            LOG_DEBUG("用户 {} 请求与用户 {} 进行通信通知", *uid, recv_id);
        }
        rsp.set_request_id(req.request_id());
        rsp.set_success(true);
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void InviteCommunicate(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(HIGH, &GatewayServer::InviteCommunicateTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response AgreeCommunicateTask(const httplib::Request &request, httplib::Response &response)
    {
        LOG_DEBUG("收到同意通话请求申请!");
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::CommunicateReq req;
        ljm::CommunicateRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户退出群聊请求正文反序列化失败！");
            return err_response("用户退出群聊请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        // 3. 响应同意通话
        for (int i = 0; i < req.receiver_id_size(); ++i)
        {
            auto recv_id = req.receiver_id(i);
            auto conn = _connections->connection(recv_id);
            if (!conn)
            {
                LOG_DEBUG("未找到接收成员 {} 长连接", recv_id);
                continue;
            }
            ljm::NotifyMessage notify;
            notify.set_notify_type(ljm::NotifyType::COMMUNICATE_NOTIFY);
            notify.mutable_communicate_notify()->set_sender_id(*uid);
            notify.mutable_communicate_notify()->set_type("response");
            notify.mutable_communicate_notify()->set_agree(true);
            conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
            LOG_DEBUG("用户 {} 同意与用户 {} 进行通信通知", *uid, recv_id);
        }
        rsp.set_request_id(req.request_id());
        rsp.set_success(true);
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void AgreeCommunicate(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(HIGH, &GatewayServer::AgreeCommunicateTask, this, request, response);
        response = futrue.get();
    }

    httplib::Response RefuseCommunicateTask(const httplib::Request &request, httplib::Response &response)
    {
        LOG_DEBUG("收到拒绝通话请求申请!");
        // 1. 取出http请求正文，将正文进行反序列化
        ljm::CommunicateReq req;
        ljm::CommunicateRsp rsp;
        auto err_response = [&req, &rsp, &response](const std::string &errmsg) -> httplib::Response
        {
            rsp.set_success(false);
            rsp.set_errmsg(errmsg);
            response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
            return response;
        };
        bool ret = req.ParseFromString(request.body);
        if (ret == false)
        {
            LOG_ERROR("用户拒绝通话请求正文反序列化失败！");
            return err_response("用户拒绝通话请求正文反序列化失败！");
        }
        // 2. 客户端身份识别与鉴权
        std::string ssid = req.session_id();
        auto uid = _redis_session->uid(ssid);
        if (!uid)
        {
            LOG_ERROR("{} 获取登录会话关联用户信息失败！", ssid);
            return err_response("获取登录会话关联用户信息失败！");
        }
        // 3. 响应拒绝通话
        for (int i = 0; i < req.receiver_id_size(); ++i)
        {
            auto recv_id = req.receiver_id(i);
            auto conn = _connections->connection(recv_id);
            if (!conn)
            {
                LOG_DEBUG("未找到接收成员 {} 长连接", recv_id);
                continue;
            }
            ljm::NotifyMessage notify;
            notify.set_notify_type(ljm::NotifyType::COMMUNICATE_NOTIFY);
            notify.mutable_communicate_notify()->set_sender_id(*uid);
            notify.mutable_communicate_notify()->set_type("response");
            notify.mutable_communicate_notify()->set_agree(false);
            conn->send(notify.SerializeAsString(), websocketpp::frame::opcode::value::binary);
            LOG_DEBUG("用户 {} 拒绝与用户 {} 进行通信通知", *uid, recv_id);
        }
        rsp.set_request_id(req.request_id());
        rsp.set_success(true);
        response.set_content(rsp.SerializeAsString(), "application/x-protbuf");
        return response;
    }

    void RefuseCommunicate(const httplib::Request &request, httplib::Response &response)
    {
        auto futrue = ThreadPoolCtrl::getInstance().submitTask(HIGH, &GatewayServer::RefuseCommunicateTask, this, request, response);
        response = futrue.get();
    }

private:
    Session::ptr _redis_session;
    Status::ptr _redis_status;

    std::string _user_service_name;
    std::string _file_service_name;
    std::string _speech_service_name;
    std::string _message_service_name;
    std::string _transmite_service_name;
    std::string _friend_service_name;

    ServiceManager::ptr _mm_channels;
    Discover::ptr _service_discoverer;

    Connection::ptr _connections;
    Connection::ptr _media_conns;

    server_t _ws_server;
    server_t _ws_media_server;
    std::thread _ws_media_thread;

    httplib::Server _http_server;
    std::thread _http_thread;
};

class GatewayServerBuilder
{
public:
    // 构造redis客户端对象
    void make_redis_object(const std::string &host,
                           int port,
                           std::string user,
                           std::string pwd,
                           int db,
                           bool keep_alive)
    {
        _redis_client = RedisClientFactory::create(host, port, user, pwd, db, keep_alive);
        if (_redis_client.get() == nullptr)
        {
            printf("_redis_client为空\n");
        }
    }
    // 用于构造服务发现客户端&信道管理对象
    void make_discovery_object(const std::string &reg_host,
                               const std::string &base_service_name,
                               const std::string &file_service_name,
                               const std::string &speech_service_name,
                               const std::string &message_service_name,
                               const std::string &friend_service_name,
                               const std::string &user_service_name,
                               const std::string &transmite_service_name)
    {
        _file_service_name = file_service_name;
        _speech_service_name = speech_service_name;
        _message_service_name = message_service_name;
        _friend_service_name = friend_service_name;
        _user_service_name = user_service_name;
        _transmite_service_name = transmite_service_name;
        _mm_channels = std::make_shared<ServiceManager>();
        _mm_channels->addCareService(file_service_name);
        _mm_channels->addCareService(speech_service_name);
        _mm_channels->addCareService(message_service_name);
        _mm_channels->addCareService(friend_service_name);
        _mm_channels->addCareService(user_service_name);
        _mm_channels->addCareService(transmite_service_name);
        auto put_cb = std::bind(&ServiceManager::addService, _mm_channels.get(), std::placeholders::_1, std::placeholders::_2);
        auto del_cb = std::bind(&ServiceManager::delService, _mm_channels.get(), std::placeholders::_1, std::placeholders::_2);
        _service_discoverer = std::make_shared<Discover>(reg_host, base_service_name, put_cb, del_cb);
    }
    void make_server_object(int websocket_port, int http_port)
    {
        _websocket_port = websocket_port;
        _http_port = http_port;
    }
    // 构造RPC服务器对象
    GatewayServer::ptr build()
    {
        if (!_redis_client)
        {
            LOG_ERROR("还未初始化Redis客户端模块！");
            abort();
        }
        if (!_service_discoverer)
        {
            LOG_ERROR("还未初始化服务发现模块！");
            abort();
        }
        if (!_mm_channels)
        {
            LOG_ERROR("还未初始化信道管理模块！");
            abort();
        }
        GatewayServer::ptr server = std::make_shared<GatewayServer>(
            _websocket_port, _http_port, _redis_client, _mm_channels,
            _service_discoverer, _user_service_name, _file_service_name,
            _speech_service_name, _message_service_name,
            _transmite_service_name, _friend_service_name);
        return server;
    }

private:
    int _websocket_port;
    int _http_port;

    std::shared_ptr<sw::redis::Redis> _redis_client;

    std::string _file_service_name;
    std::string _speech_service_name;
    std::string _message_service_name;
    std::string _friend_service_name;
    std::string _user_service_name;
    std::string _transmite_service_name;
    ServiceManager::ptr _mm_channels;
    Discover::ptr _service_discoverer;
};